package mahjong;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

/** 
 * Menu bar for the GUI, handles all options in menu form
 * 
 */
public class MenuManager implements ActionListener {

	/** Menu item for save function*/
	private JMenuItem save;
	/** Menu item for open function*/
	private JMenuItem open;
	/** Menu item for cheatai function*/
	private JMenuItem cheatai;
	/** Menu item for smartai function*/
	private JMenuItem smartai;
	/** Menu item for randomai function*/
	private JMenuItem randomai;
	private JMenuItem montecarloai;
	/** Menu item for stopai function*/
	private JMenuItem stopai;
	/** Menu item for hint function*/
	private JMenuItem hint;
	/** Menu item for undo function*/
	private JMenuItem undo;
	/** Menu item for redo function*/
	private JMenuItem redo;
	/** Menu item for pause function*/
	private JMenuItem pause;
	/** Menu item for cont function*/
	private JMenuItem cont;
	/** Menu item for highscores function*/
	private JMenuItem highscores;
	/** Menu item for quit function*/
	private JMenuItem quit;
	/** Menu item for ziglayout */
	private JMenuItem ziglayout;
	/** Menu item for turtle layout **/
	private JMenuItem turtlelayout;
	/** Menu item for ai function*/
	private JMenu ai;

	/** Viewer on with to act*/
	private Viewer d;
	/** Clock */
	private TimeManager tm;
	/** Filechooser for opening and saving files */
	private static final JFileChooser fc = new JFileChooser();
	/**
	 * Constructor for Menumanager
	 * @param v frame
	 * @param drawarea board area
	 * @param timer clock
	 */
	public MenuManager(JViewer v, Viewer drawarea, TimeManager timer)
	{
		
		fc.addChoosableFileFilter(new GameFilter());
		d = drawarea;
		tm = timer;
		
		JMenuBar menuBar = new JMenuBar();
		
		// adding all items to menu
		// FILE - OPEN / SAVE
		JMenu file = new JMenu("FILE");
		menuBar.add(file);
		//NEW GAME
		JMenu newgame = new JMenu("New Game");
		newgame.getAccessibleContext().setAccessibleDescription("Creates a new game. All unsaved progress will be lost.");
		turtlelayout = new JMenuItem("Turtle Layout");
		turtlelayout.getAccessibleContext().setAccessibleDescription("Creates a new game with ziggurat layout.");
		turtlelayout.addActionListener(this);
		newgame.add(turtlelayout);
		ziglayout = new JMenuItem("Ziggurat Layout");
		ziglayout.getAccessibleContext().setAccessibleDescription("Creates a new game with ziggurat layout.");
		ziglayout.addActionListener(this);
		newgame.add(ziglayout);
		file.add(newgame);
		file.addSeparator();
		
		//OPEN - SAVE GAME
		open = new JMenuItem("Open");
		open.getAccessibleContext().setAccessibleDescription("Open a saved game. Using this feature will not let you submit to the highscore list.");
		open.addActionListener(this);
		file.add(open);
		save = new JMenuItem("Save", KeyEvent.VK_S);
		save.getAccessibleContext().setAccessibleDescription("Save the current game. Using this feature will not let you submit to the highscore list.");
		save.addActionListener(this);
		file.add(save);
		file.addSeparator();
		
		//PAUSE - CONTINUE
		pause = new JMenuItem("Pause");
		pause.getAccessibleContext().setAccessibleDescription("Pause the current game.");
		pause.addActionListener(this);
		file.add(pause);
		cont = new JMenuItem("Continue");
		cont.getAccessibleContext().setAccessibleDescription("Continue the game.");
		cont.addActionListener(this);
		file.add(cont);
		file.addSeparator();
		
		//HIGHSCORES
		highscores = new JMenuItem("Highscores");
		highscores.getAccessibleContext().setAccessibleDescription("Shows the highscores for the current layout.");
		highscores.addActionListener(this);
		file.add(highscores);
		file.addSeparator();
		
		//EXIT
		quit = new JMenuItem("Exit");
		quit.getAccessibleContext().setAccessibleDescription("Quit the game. All unsaved progress will be lost.");
		quit.addActionListener(this);
		file.add(quit);
		
		// EDIT MENU
		JMenu edit = new JMenu("Edit");
		menuBar.add(edit);
		undo = new JMenuItem("Undo");
		undo.getAccessibleContext().setAccessibleDescription("Undo the previous move. Using this feature will not let you submit to the highscore list.");
		undo.addActionListener(this);
		edit.add(undo);
		redo = new JMenuItem("Redo");
		redo.getAccessibleContext().setAccessibleDescription("Redo any undone moves. Using this feature will not let you submit to the highscore list.");
		redo.addActionListener(this);
		edit.add(redo);
		JMenu help = new JMenu("Help");
		menuBar.add(help);
		hint = new JMenuItem("Hint");
		hint.getAccessibleContext().setAccessibleDescription("Toggles the hint mode. Using this feature will not let you submit to the highscore list.");
		hint.addActionListener(this);
		help.add(hint);
		help.addSeparator();
		
		ai = new JMenu("Add AI");
		help.add(ai);
		cheatai = new JMenuItem("Cheat AI");
		cheatai.getAccessibleContext().setAccessibleDescription("Turns on the cheating AI. Using this feature will not let you submit to the highscore list.");
		cheatai.addActionListener(this);
		ai.add(cheatai);
		montecarloai = new JMenuItem("Monte Carlo AI");
		montecarloai.getAccessibleContext().setAccessibleDescription("Turns on the Monte Carlo AI. Using this feature will not let you submit to the highscore list.");
		montecarloai.addActionListener(this);
		ai.add(montecarloai);
		smartai = new JMenuItem("Smart AI");
		smartai.getAccessibleContext().setAccessibleDescription("Turns on the smart AI. Using this feature will not let you submit to the highscore list.");
		smartai.addActionListener(this);
		ai.add(smartai);
		randomai = new JMenuItem("Random AI");
		randomai.getAccessibleContext().setAccessibleDescription("Turns on the random AI. Using this feature will not let you submit to the highscore list.");
		randomai.addActionListener(this);
		ai.add(randomai);
		
		stopai = new JMenuItem("Stop AI");
		stopai.getAccessibleContext().setAccessibleDescription("Stops the current AI.");
		stopai.addActionListener(this);
		stopai.setEnabled(false);
		help.add(stopai);
		v.setJMenuBar(menuBar);

	}
	
	/**
	 * Event handler for the menu
	 */
	public void actionPerformed(ActionEvent e) {
		if(e.getSource().equals(save))
		{
			
			hint.setEnabled(true);
			undo.setEnabled(true);
			redo.setEnabled(true);
			ai.setEnabled(true);
			stopai.setEnabled(false);
			d.getBoard().stopAutoPlay();
			d.repaint();
			
			//stop timer while saving game
			GameTime.stopTimer();
			//UI for saving game
			if (fc.showSaveDialog(d) == JFileChooser.APPROVE_OPTION) 
			{
		            File file = fc.getSelectedFile();
		            FileOutputStream f_out = null;
					try 
					{
						//Ensure the file to save ends with .maj
						String s = file.getName();
						int j = s.lastIndexOf('.');
				        if (j > 0 &&  j < s.length() - 1) 
				        {
				            String extension = s.substring(j+1).toLowerCase();
				            if ("maj".equals(extension)) 
				            {
				            	f_out = new FileOutputStream(file);
				            }
				        }
				        else
				        {
				        	f_out = new FileOutputStream(file.getAbsolutePath()+".maj");
				        }
			            ObjectOutputStream obj_out = new ObjectOutputStream (f_out);
			            Board b = d.getBoard();
			            b.saveGameTime(GameTime.timeToInt());
			            obj_out.writeObject (d.getBoard());
					} catch (Exception exc) {
						System.out.println("There was an error saving the game. Please try again.");
					} 
	        }
			
			//resume
			GameTime.startTimer();
		}
		else if(e.getSource().equals(open))
		{
			hint.setEnabled(true);
			undo.setEnabled(true);
			redo.setEnabled(true);
			ai.setEnabled(true);
			stopai.setEnabled(false);
			d.getBoard().stopAutoPlay();
			d.repaint();
			
			//UI for opening game
			if (fc.showOpenDialog(d) == JFileChooser.APPROVE_OPTION) 
			{
		            File file = fc.getSelectedFile();
		            InputStream f_in = null;
					try {
						
						//Ensure the file to save ends with .maj
						String s = file.getName();
						int j = s.lastIndexOf('.');
				        if (j > 0 &&  j < s.length() - 1) 
				        {
				            String extension = s.substring(j+1).toLowerCase();
				            if ("maj".equals(extension)) 
				            {
				            	f_in = new FileInputStream(file);
				            }
				        }
				        else
				        {
				        	f_in = new FileInputStream(file.getAbsolutePath()+".maj");
				        }
				        
						ObjectInputStream obj_in = new ObjectInputStream(f_in);
			            Object obj = obj_in.readObject();
			            if(obj instanceof Board)
			            {
			            	GameTime.stopTimer();
			            	Board b = (Board) obj;
			            	d.setBoard(b);
			            	d.repaint();
			            	GameTime.setTimer(b.getGameTime());
			            	tm.resetTimeLabel();
			            	GameTime.startTimer();
			            }
					}catch(Exception exc)
					{
						System.out.println(exc.toString());
						System.out.println("There was an error loading the game file. Please try again.");
					}
	        }
			d.cont();
			hint.setEnabled(true);
			undo.setEnabled(true);
			redo.setEnabled(true);
			pause.setEnabled(true);
			ai.setEnabled(true);
			stopai.setEnabled(false);
			//disable HS
			d.getBoard().setHS(false);
		}
		else if(e.getSource().equals(quit))
		{
			System.exit(0);
		}
		else if(e.getSource().equals(pause))
		{
			d.pause();
			hint.setEnabled(false);
			undo.setEnabled(false);
			redo.setEnabled(false);
			pause.setEnabled(false);
			d.repaint();
		}
		else if(e.getSource().equals(cont))
		{
			d.cont();
			if(ai.isEnabled())
			{
				hint.setEnabled(true);
				undo.setEnabled(true);
				redo.setEnabled(true);
			}
			pause.setEnabled(true);
			d.repaint();
		}
		else if(e.getSource().equals(highscores))
		{
			HighScoreHandler.displayHighScores(d.getBoard().getBName(), d);
		}
		else if(e.getSource().equals(hint))
		{
			d.switchHintMode();
			d.repaint();
			//Disable HS
			d.getBoard().setHS(false);
		}
		else if(e.getSource().equals(undo))
		{
			d.undo();
			d.repaint();
			//disable HS
			d.getBoard().setHS(false);
		}
		else if(e.getSource().equals(redo))
		{
			d.redo();
			d.repaint();
		}
		else if(e.getSource().equals(cheatai))
		{
			hint.setEnabled(false);
			undo.setEnabled(false);
			redo.setEnabled(false);
			ai.setEnabled(false);
			stopai.setEnabled(true);
			d.getBoard().startAutoPlay(d, 2);
			//disable HS
			d.getBoard().setHS(false);
			if(d.isHintMode()) d.switchHintMode();
			d.cont();
			pause.setEnabled(true);
			d.repaint();
		}
		else if(e.getSource().equals(montecarloai))
		{
			hint.setEnabled(false);
			undo.setEnabled(false);
			redo.setEnabled(false);
			ai.setEnabled(false);
			stopai.setEnabled(true);
			d.getBoard().startAutoPlay(d, 0);
			//disable HS
			d.getBoard().setHS(false);
			if(d.isHintMode()) d.switchHintMode();
			d.cont();
			pause.setEnabled(true);
			d.repaint();
		}
		else if(e.getSource().equals(smartai))
		{
			hint.setEnabled(false);
			undo.setEnabled(false);
			redo.setEnabled(false);
			ai.setEnabled(false);
			stopai.setEnabled(true);
			d.getBoard().startAutoPlay(d, 1);
			//disable HS
			d.getBoard().setHS(false);
			if(d.isHintMode()) d.switchHintMode();
			d.cont();
			pause.setEnabled(true);
			d.repaint();
		}
		else if(e.getSource().equals(randomai))
		{
			hint.setEnabled(false);
			undo.setEnabled(false);
			redo.setEnabled(false);
			ai.setEnabled(false);
			stopai.setEnabled(true);
			d.getBoard().startAutoPlay(d, 3);
			//disable HS
			d.getBoard().setHS(false);
			d.getBoard().hint(false);
			if(d.isHintMode()) d.switchHintMode();
			d.cont();
			pause.setEnabled(true);
			d.repaint();
		}
		else if (e.getSource().equals(stopai))
		{
			hint.setEnabled(true);
			undo.setEnabled(true);
			redo.setEnabled(true);
			ai.setEnabled(true);
			stopai.setEnabled(false);
			d.getBoard().stopAutoPlay();
			d.repaint();
		}
		else if(e.getSource().equals(ziglayout))
		{
			//reset everything
			d.cont();
			hint.setEnabled(true);
			undo.setEnabled(true);
			redo.setEnabled(true);
			pause.setEnabled(true);
			stopai.setEnabled(false);
			d.reset(1);
			d.repaint();
			GameTime.resetTimer();
			tm.resetTimeLabel();
			d.getBoard().setHS(true);
		}
		else if(e.getSource().equals(turtlelayout))
		{
			d.cont();
			hint.setEnabled(true);
			undo.setEnabled(true);
			redo.setEnabled(true);
			pause.setEnabled(true);
			stopai.setEnabled(false);
			d.reset(0);
			d.repaint();
			GameTime.resetTimer();
			tm.resetTimeLabel();
			d.getBoard().setHS(true);
		}
	}


	

}
